package fr.imag.ufrima.ctte;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.util.ArrayList;
import java.util.List;

import fr.imag.ufrima.ctte.enums.OperatorTypes;
/**
 * Operator class
 * This is the data structure that represent an operator
 * An operator is represented by its type and the two tasks that wires. 
 * 
 * @author Bassem DEBBABI
 *
 */
public class Operator {
	
	// structure properties
	private OperatorTypes type;
	private Task startTask;
	private Task endTask;
	private TaskDiagram taskDiagram;
	
	// static icons
	private final static Image ChoiceImg = Toolkit.getDefaultToolkit().getImage("images\\choice.gif");
	private final static Image OrderImg = Toolkit.getDefaultToolkit().getImage("images\\order.gif");
	private final static Image ConcurrentImg = Toolkit.getDefaultToolkit().getImage("images\\interleave.gif");
	private final static Image ConcurrentInfoExchangeImg = Toolkit.getDefaultToolkit().getImage("images\\sincro.gif");
	private final static Image DisablingImg = Toolkit.getDefaultToolkit().getImage("images\\disabling.gif");
	private final static Image SuspendImg = Toolkit.getDefaultToolkit().getImage("images\\suspend.gif");
	private final static Image EnablingImg = Toolkit.getDefaultToolkit().getImage("images\\enabling.gif");
	private final static Image EnablingInfoExchangeImg = Toolkit.getDefaultToolkit().getImage("images\\enablinginfo.gif");
	
	/**
	 * Constructor
	 * @param taskDiagram parent task diagram
	 * @param type 		  operator type
	 * @param startTask   starting task
	 * @param endTask     ending task
	 */
	public Operator(TaskDiagram taskDiagram, OperatorTypes type, Task startTask, Task endTask){
		// TODO verify that startTask and endTask are not null
		this.taskDiagram = taskDiagram;
		this.type = type;
		this.startTask = startTask;
		startTask.setRightOperator(this);
		this.endTask = endTask;
		endTask.setLeftOperator(this);
	}
	public void remove(){
		this.startTask.setRightOperator(null);
		this.endTask.setLeftOperator(null);
		this.setStartTask(null);
		this.setEndTask(null);
		this.taskDiagram = null;
	}
	public void setType(String type){
		
			if (type.equals("Choice"))
				this.type = OperatorTypes.CHOICE;		
			else if (type.equals("Concurrent"))
					this.type = OperatorTypes.CONCURRENT;		
			else if (type.equals("Concurrent with info exchange"))
					this.type = OperatorTypes.CONCURRENT_WITH_INFO_EXCHANGE;		
			else if (type.equals("CTT Disabling"))
					this.type = OperatorTypes.CTT_DISABLING;		
			else if (type.equals("Enabling"))
					this.type = OperatorTypes.ENABLING;		
			else if (type.equals("Enabling with info exchange"))
					this.type = OperatorTypes.ENABLING_WITH_INFO_EXCHANGE;
			else if (type.equals("Order Independency"))
					this.type = OperatorTypes.ORDER_INDEPENDENCY;
			else if (type.equals("Suspend/Resume"))
					this.type = OperatorTypes.SUSPEND_RESUME;			
			taskDiagram.fireOperatorPropertiesChangedEvent(this);
	}
	public String getTypeAsString(){
		if (type == OperatorTypes.CHOICE)
			return "Choice";
		else if (type == OperatorTypes.CONCURRENT)
			return "Concurrent";
		else if (type == OperatorTypes.CONCURRENT_WITH_INFO_EXCHANGE)
			return "Concurrent with info exchange";
		else if (type == OperatorTypes.CTT_DISABLING)
			return "CTT Disabling";
		else if (type == OperatorTypes.ENABLING)
			return "Enabling";
		else if (type == OperatorTypes.ENABLING_WITH_INFO_EXCHANGE)
			return "Enabling with info exchange";
		else if (type == OperatorTypes.ORDER_INDEPENDENCY)
			return "Order Independency";
		else if (type == OperatorTypes.SUSPEND_RESUME)
			return "Suspend/Resume";
		else 
			return "";
	}
	public List<String> getOperatorTypes(){
		List<String> types = new ArrayList<String>();
		types.add("Choice");
		types.add("Order Independency");
		types.add("Concurrent");
		types.add("Concurrent with info exchange");
		types.add("CTT Disabling");
		types.add("Suspend/Resume");
		types.add("Enabling");
		types.add("Enabling with info exchange");
		
		return types;
	}
	/**
	 * Draw the operator
	 * @param g2d graphic object
	 */
	public void draw(Graphics2D g2d){
		if (startTask != null && endTask != null){
			// 1. draw the line
			g2d.drawLine(startTask.getPosition().x, 
					startTask.getPosition().y, 
					endTask.getPosition().x, 
					endTask.getPosition().y);
			// 2. draw the shape 
			Image img = null;
			switch(this.type){
			case CHOICE:
				img = ChoiceImg; break;
			case CONCURRENT:
				img = ConcurrentImg; break;
			case CONCURRENT_WITH_INFO_EXCHANGE:
				img = ConcurrentInfoExchangeImg; break;
			case CTT_DISABLING:
				img = DisablingImg; break;
			case ENABLING:
				img = EnablingImg; break;
			case ENABLING_WITH_INFO_EXCHANGE:
				img = EnablingInfoExchangeImg; break;
			case ORDER_INDEPENDENCY:
				img = OrderImg; break;
			case SUSPEND_RESUME:
				img = SuspendImg; break;
			default:
				img = ChoiceImg; break;
			}			
			java.awt.Color c = g2d.getColor();
			g2d.setColor(Color.WHITE);
			g2d.fillRect(startTask.getPosition().x + 
					(endTask.getPosition().x - startTask.getPosition().x)/2 - taskDiagram.getOperatorWidth()/2, 
					startTask.getPosition().y - taskDiagram.getOperatorHeight()/2, 
					16, 16);
			g2d.setColor(c);
			g2d.drawImage(img, startTask.getPosition().x + 
					(endTask.getPosition().x - startTask.getPosition().x)/2 - taskDiagram.getOperatorWidth()/2, 
					startTask.getPosition().y - taskDiagram.getOperatorHeight()/2, 
					taskDiagram.getOperatorWidth(), taskDiagram.getOperatorHeight(),null);			
		}
	}
	/**
	 * draw selected operator
	 * @param g2d graphic object
	 */
	public void drawSelected(Graphics2D g2d){
		if (taskDiagram != null && startTask != null && endTask != null){
			int x1 = startTask.getPosition().x + (taskDiagram.getNodeWidth()/2 );
			int y1 = startTask.getPosition().y - (taskDiagram.getOperatorHeight()/2);
			int x2 = endTask.getPosition().x - (taskDiagram.getNodeWidth()/2);
			int y2 = endTask.getPosition().y + (taskDiagram.getOperatorHeight()/2);		
			java.awt.Color c = g2d.getColor();	
			g2d.setColor(java.awt.Color.RED);
			g2d.drawRoundRect(x1, y1, 
					x2 - x1, y2 - y1, 10, 10);		
			g2d.setColor(c);
		}
	}
	
	/**
	 * draw hinted operator
	 * @param g2d graphic object
	 */
	/*
	public void drawHinted(Graphics2D g2d){
		int x1 = this.getStartTask().getPosition().x + (taskDiagram.getNodeWidth()/2 );
		int y1 = this.getStartTask().getPosition().y - (taskDiagram.getOperatorHeight()/2);
		int x2 = this.getEndTask().getPosition().x - (taskDiagram.getNodeWidth()/2);
		int y2 = this.getEndTask().getPosition().y + (taskDiagram.getOperatorHeight()/2);		
		java.awt.Color c = g2d.getColor();	
		g2d.setColor(Color.RED);
		g2d.drawRoundRect(x1, y1, 
				x2 - x1, y2 - y1, 10, 10);		
		g2d.setColor(c);
	}*/
	/**
	 * get the starting task
	 * @return starting task of the operator
	 */
	public Task getStartTask() {
		return startTask;
	}
	/**
	 * setting the starting task
	 * @param startTask new task
	 */
	public void setStartTask(Task startTask) {
		this.startTask = startTask;
	}
	/**
	 * get the ending task
	 * @return ending task of the operator
	 */
	public Task getEndTask() {
		return endTask;
	}
	/**
	 * setting the ending task
	 * @param endTask new task
	 */
	public void setEndTask(Task endTask) {
		this.endTask = endTask;
	}
}
